#ifndef TILE
#define TILE

#include <base\vec2i.h>
#include <base\vec3f.h>
#include <render\viewFrustum.h>

#include <cache\textureCacheKey.h>
#include <cache\terrainCacheKey.h>

#include <app\states\modelInfoState.h>

#include <boost/thread/condition_variable.hpp>
#include <boost/shared_ptr.hpp>

struct s_download_query;

/**
 * Data storage
 */
class tile {

  modelInfoState *mi_state;

  vec2i tile_id;
  vec2i viewer_position;
  vec2i start_position;

  vec2i patch_size;
  viewFrustum vf;

  int level;
  bool visible;
  float distance;

  boost::mutex download_mutex;

private:

  enum e_layer_state {
    AVAILABLE,
    GENERATED_FROM_COARSER,
    TO_BE_DOWNLOADED,
    DOWNLOADING,
    MISSING
  };

  e_layer_state terrain_state;
  e_layer_state texture_state;

  textureCacheKey *tex_cache;
  terrainCacheKey *ter_cache;

private:

  boost::shared_ptr<tile> * searchForCoarserTile(vector<boost::shared_ptr<tile> *> *coarse_tiles, vec2i finer_tile_id);
  bool generateTerrainForFinerTile(tile *finer_tile, vec2i finer_tile_id, int finer_level);

public:

  unsigned short **getTerrainRows();
  unsigned char  **getTextureRows();

  void selectedToDownload();
  void terrainDownloaded();
  void setVisible(viewFrustum vf_);
  bool equals(vec2i tile_id_);
  bool isVisible();

  s_download_query getDownloadQuery();

  tile(vector<vector<boost::shared_ptr<tile> *> > *all_loaded_tiles_, vec2i to_position_l_, vec2i tile_id_, vec2i start_position_, vec2i patch_size_, int level_, modelInfoState *mi_state_);
  ~tile();
};

#endif